//
//  UIButton+Extension.swift
//  DoctorEPlus
//
//  Created by 王林波 on 2020/10/27.
//

import Foundation
import UIKit

extension UIButton {
    typealias BtnAction = (UIButton)->()

    
    private struct touchEdgeInsetKey{
        static var touchEdgeInsetKey = "bh_button_touchEdginsetKey"
    }
    
    private struct AssociatedKeys{
       static var actionKey = "actionKey"
    }
    
    private struct delayTouchKey{
       static var delayTouchKey = "delayTouchKey"
    }
     
     @objc dynamic var actionDic: NSMutableDictionary? {
         set{
             objc_setAssociatedObject(self,&AssociatedKeys.actionKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY)
         }
         get{
             if let dic = objc_getAssociatedObject(self, &AssociatedKeys.actionKey) as? NSDictionary{
                 return NSMutableDictionary.init(dictionary: dic)
             }
             return nil
         }
     }
    
     dynamic var delayTouch: Bool? {
        set{
            objc_setAssociatedObject(self,&delayTouchKey.delayTouchKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
        }
        get{
            if let key = objc_getAssociatedObject(self, &delayTouchKey.delayTouchKey) as? Bool{
                return key
            }
            return false
        }
    }
    
    dynamic var enlargeEdgeInset: UIEdgeInsets {
        set {
            objc_setAssociatedObject(self,&touchEdgeInsetKey.touchEdgeInsetKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY)
        }get {
            if let key = objc_getAssociatedObject(self, &touchEdgeInsetKey.touchEdgeInsetKey) as? UIEdgeInsets{
                return key
            }
            return .zero
        }
    }
    
    

     @objc dynamic  func addBtnAction(action:@escaping  BtnAction ,for controlEvents: UIControl.Event) {
         let eventStr = NSString.init(string: String.init(describing: controlEvents.rawValue))
         if let actions = self.actionDic {
             actions.setObject(action, forKey: eventStr)
             self.actionDic = actions
         }else{
             self.actionDic = NSMutableDictionary.init(object: action, forKey: eventStr)
         }
             

         switch controlEvents {
             case .touchUpInside:
                 self.addTarget(self, action: #selector(touchUpInSideBtnAction), for: .touchUpInside)
             case .touchUpOutside:
                 self.addTarget(self, action: #selector(touchUpOutsideBtnAction), for: .touchUpOutside)
         default: break
             
         }
       }

       @objc fileprivate func touchUpInSideBtnAction(btn: UIButton) {
           if let actionDic = self.actionDic  {
             if let touchUpInSideAction = actionDic.object(forKey: String.init(describing: UIControl.Event.touchUpInside.rawValue)) as? BtnAction{
                   touchUpInSideAction(self)
                }
           }
       }

       @objc fileprivate func touchUpOutsideBtnAction(btn: UIButton) {
          if let actionDic = self.actionDic  {
             if let touchUpOutsideBtnAction = actionDic.object(forKey:   String.init(describing: UIControl.Event.touchUpOutside.rawValue)) as? BtnAction{
                 touchUpOutsideBtnAction(self)
             }
          }
       }
    
    func enlargedRect() -> CGRect {
            
        if self.enlargeEdgeInset != .zero {
            return CGRect.init(x: self.bounds.origin.x - CGFloat(self.enlargeEdgeInset.left),
                                   y: self.bounds.origin.y - CGFloat(self.enlargeEdgeInset.top),
                                   width: self.bounds.size.width + CGFloat(self.enlargeEdgeInset.left) + CGFloat(self.enlargeEdgeInset.right),
                                   height: self.bounds.size.height + CGFloat(self.enlargeEdgeInset.top) + CGFloat(self.enlargeEdgeInset.bottom))
        }
        else {
            return self.bounds
        }
    }

    
    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
           let rect = self.enlargedRect()
           if rect.equalTo(self.bounds) {
               return super.point(inside: point, with: event)
           }
           return rect.contains(point) ? true : false
       }
}
